package com.zhang.config;

import com.zhang.service.MyUserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;


@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private MyUserDetailService userDetailsService;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private PersistentTokenRepository persistentTokenRepository;

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        //jdbcTokenRepository.setCreateTableOnStartup(true); //启动时自动创建数据库表  persistent_logins (当表创建好后,就注释掉它)
        return jdbcTokenRepository;
    }

    //1.安全过滤器链配置方法
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //1.路径拦截
        http.authorizeRequests()
                //不需要登录
                .antMatchers("/user/index").permitAll()
                //需要登录
                .antMatchers("/user/demo1").authenticated()
                //需要登录+授权
                .antMatchers("/user/demo3").hasAnyAuthority("aaa")
                //需要登录 (所有的请求都需要先登录后才可访问)
                .anyRequest().authenticated();


        //2.自定义登录页(当需要需要登录+授权的,就跳转到登录页面)
        http.formLogin()
                .loginPage("/login.html")//登录页
                .loginProcessingUrl("/user/login")//登录路径(security的路径)
                .defaultSuccessUrl("/user/success")//登录成功后
                .failureUrl("/user/error")//登录失败后
                .permitAll();

        //3.退出
        http.logout()
                .logoutUrl("/logout")//退出路径(security的路径)
                .logoutSuccessUrl("/user/index")//退出后跳转的路径
                .permitAll();

        //4.记住我
        http.rememberMe()
                .tokenRepository(persistentTokenRepository)//操作数据库对象
                .tokenValiditySeconds(60)//设置有效时长
                .userDetailsService(userDetailsService);


        //5.自定义403 (当登录成功后,还是没有权限访问,就跳转到403)
        http.exceptionHandling().accessDeniedPage("/unauth.html");


        //6.关闭csrf
        http.csrf().disable();
    }
    //2.核心过滤器配置方法
    @Override
    public void configure(WebSecurity web) throws Exception {

    }
    //3.认证管理器配置方法
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(password());
    }



    //这里指定了BCryptPasswordEncoder加密器 , 那么在进行明文与密文匹配的时候就会采用该种加密器进行处理
    @Bean
    public PasswordEncoder password() {
        return new BCryptPasswordEncoder();
    }


}









